package org.jsola.hr.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.jsola.core.Page;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.constant.RemindUnitEnum;
import org.jsola.hr.dao.IMemoConfigDAO;
import org.jsola.hr.dto.MemoConfigAddDTO;
import org.jsola.hr.dto.MemoConfigUpdateDTO;
import org.jsola.hr.dto.MemoInfoAddDTO;
import org.jsola.hr.dto.MemoInfoUpdateDTO;
import org.jsola.hr.entity.MemoConfigDO;
import org.jsola.hr.entity.MemoInfoDO;
import org.jsola.hr.query.MemoConfigQuery;
import org.jsola.hr.service.IMemoConfigService;
import org.jsola.hr.service.IMemoInfoService;
import org.jsola.hr.vo.MemoConfigListVO;
import org.jsola.hr.vo.MemoConfigVO;
import org.jsola.hr.vo.MemoInfoVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 备忘录配置
 *
 * @author zhr
 */
@Service("hrMemoConfigServiceImpl")
public class MemoConfigServiceImpl implements IMemoConfigService {

    public static final String DAY = "DAY";
    public static final String WEEK = "WEEK";
    public static final String MONTH = "MONTH";
    public static final String YEAR = "YEAR";

    @Autowired
    private IMemoConfigDAO memoConfigDAO;

    @Autowired
    private IMemoInfoService memoInfoService;



    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public MemoConfigVO save(MemoConfigAddDTO memoConfigAddDTO, TokenUser tokenUser) {
        // 转DO
        MemoConfigDO memoConfigDO = memoConfigAddDTO.to(MemoConfigDO.class);
        // 保存
        memoConfigDO = save(memoConfigDO, tokenUser.getSiteId(), tokenUser.getUserId());

        //根据配置生成备忘录详情
        buildMemoInfo(memoConfigDO, tokenUser);

        return memoConfigDO.to(MemoConfigVO.class);
    }

    /**
     * 根据备忘录配置，生成备忘录数据
     * @param memoConfigDO
     * @param tokenUser
     */
    private void buildMemoInfo(MemoConfigDO memoConfigDO, TokenUser tokenUser) {
        Integer remindType = memoConfigDO.getRemindType();
        switch (remindType){
            case 1:
                //固定日期提醒
                MemoInfoAddDTO memoInfoAddDTO = memoConfigDO.to(MemoInfoAddDTO.class);
                memoInfoAddDTO.setConfigId(memoConfigDO.getId());
                memoInfoService.save(memoInfoAddDTO, tokenUser);
                break;
            case 2:
                //周期性提醒
                List<MemoInfoAddDTO> list = buildMemoInfoByCalendar(memoConfigDO);
                for (MemoInfoAddDTO infoAddDTO : list) {
                    memoInfoService.save(infoAddDTO, tokenUser);
                }
//                memoInfoService.batchSave(list, tokenUser);
                break;
            default:

        }
    }

    /**
     * 根据周期性备忘录配置，身材隔行备忘录数据
     * @param memoConfigDO
     * @return
     */
    private List<MemoInfoAddDTO> buildMemoInfoByCalendar(MemoConfigDO memoConfigDO) {
        List<MemoInfoAddDTO> result = new ArrayList<>();
        String remindunit = memoConfigDO.getRemindUnit();
        switch (remindunit){
            case DAY:
                //每X天生成一条备忘录
                break;
            case WEEK:
                //每周几生成一条备忘录
                break;
            case MONTH:
                //每月几号生成一条备忘录
                String remindMonthUnitValue = memoConfigDO.getRemindMonthUnitValue();
                if (StringUtils.isNotBlank(remindMonthUnitValue)) {
                    String[] remindMonthUnitValueList = remindMonthUnitValue.split(",");
                    //查询日期集合
                    List<LocalDate> dateList = calcDateByDay(remindMonthUnitValueList);
                    if (!CollectionUtils.isEmpty(dateList)) {
                        for (LocalDate localDate : dateList) {
                            MemoInfoAddDTO memoInfoAddDTO = memoConfigDO.to(MemoInfoAddDTO.class);
                            memoInfoAddDTO.setConfigId(memoConfigDO.getId());
                            memoInfoAddDTO.setCompleted(false);
                            memoInfoAddDTO.setRemindDate(DateUtils.locaDateToDate(localDate));
                            memoInfoAddDTO.setRemindTime(memoConfigDO.getRemindTime());
                            result.add(memoInfoAddDTO);
                        }
                    }
                }
                break;
            case YEAR:
                //每X年生成一条记录
                break;
            default:
        }
        return result;
    }

    /**
     * 根据每月第几天，计算当前时间至年底的所有日期
     * @param remindMonthUnitValueList
     * @return
     */
    private List<LocalDate> calcDateByDay(String[] remindMonthUnitValueList) {
        List<LocalDate> result = new ArrayList<>();
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        Month nowMonth = now.getMonth();
        LocalDate tmpLocalDate = LocalDate.now();
        //当前年的最后一天
        LocalDate lastDay  = LocalDate.now().with(TemporalAdjusters.lastDayOfYear());
        while (tmpLocalDate.compareTo(lastDay) <= 0) {
            for (String s : remindMonthUnitValueList) {
                //判断某一天，这个分月是否有，比如31号
                int maxlength =  nowMonth.maxLength();
                if (Integer.parseInt(s) > maxlength) {
                    continue;
                }
                tmpLocalDate = LocalDate.of(year, nowMonth, Integer.parseInt(s));
                //通知时间 》= 0 当前时间保留
                if (now.compareTo(tmpLocalDate) <= 0) {
                    result.add(tmpLocalDate);
                }
            }
            nowMonth = nowMonth.plus(1);
            tmpLocalDate = tmpLocalDate.plusMonths(1);
        }
        return result;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(MemoConfigUpdateDTO memoConfigUpdateDTO, TokenUser tokenUser) {
        //转DO
        MemoConfigDO memoConfigDO = memoConfigUpdateDTO.to(MemoConfigDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(memoConfigDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... memoConfigIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) memoConfigIds);
    }


    @Override
    public MemoConfigVO selectById(String memoConfigId, String siteId) {
        MemoConfigDO memoConfigDO = selectDOById(memoConfigId, siteId);
        if (memoConfigDO == null) {
            return null;
        }
        return memoConfigDO.to(MemoConfigVO.class);
    }

    @Override
    public List<MemoConfigListVO> select(MemoConfigQuery memoConfigQuery, String siteId) {
        List<MemoConfigDO> memoConfigDOList = selectDO(memoConfigQuery, siteId);
        if(CollectionUtils.isEmpty(memoConfigDOList)) {
            return memoConfigDOList == null ? null : new ArrayList<>();
        }
        return memoConfigDOList.stream()
                .map(memoConfigDO -> memoConfigDO.to(MemoConfigListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(MemoConfigQuery memoConfigQuery, String siteId) {
        Example example = buildExample(memoConfigQuery,siteId);
        return memoConfigDAO.selectCountByExample(example);
    }

    @Override
    public Page<MemoConfigListVO> selectPage(MemoConfigQuery memoConfigQuery, String siteId) {
        Example example = buildExample(memoConfigQuery,siteId);
        Page<MemoConfigDO> page = memoConfigDAO.selectPageByExample(example,
                memoConfigQuery.getPageNo(),
                memoConfigQuery.getPageSize());

        return page.to(MemoConfigListVO.class);
    }

    @Override
    public MemoConfigDO selectDOById(String memoConfigId, String siteId) {
        return listById(memoConfigId, siteId);
    }

    @Override
    public List<MemoConfigDO> selectDO(MemoConfigQuery memoConfigQuery, String siteId) {
        Example example = buildExample(memoConfigQuery,siteId);
        return memoConfigDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void updateByMemoId(MemoInfoUpdateDTO memoInfoUpdateDTO, TokenUser tokenUser) {
        String memoId = memoInfoUpdateDTO.getId();
        MemoInfoVO memoInfoVO = memoInfoService.selectById(memoId, tokenUser.getSiteId());
        String configId = memoInfoVO.getConfigId();
        if (StringUtils.isNotBlank(configId)) {
            // 更新备忘录配置
            MemoConfigDO memoConfigDO = new MemoConfigDO();
            memoConfigDO.setId(configId);
            memoConfigDO.setCompanyId(memoInfoUpdateDTO.getCompanyId());
            memoConfigDO.setRemindType(memoInfoUpdateDTO.getRemindType());
            memoConfigDO.setRemindNeed(true);
            memoConfigDO.setRemindBefore(1);
            memoConfigDO.setContent(memoInfoUpdateDTO.getContent());
            if (memoInfoUpdateDTO.getRemindType() == 1) {
                memoConfigDO.setRemindDate(memoInfoUpdateDTO.getRemindDate());
                memoConfigDO.setRemindTime(memoInfoUpdateDTO.getRemindTime());
            } else if (memoInfoUpdateDTO.getRemindType() == 2) {
                memoConfigDO.setRemindTime(memoInfoUpdateDTO.getRemindTime());
                memoConfigDO.setRemindMonthUnitValue(memoInfoUpdateDTO.getRemindMonthUnitValue());
                memoConfigDO.setRemindUnit(memoInfoUpdateDTO.getRemindUnit());
            }
            updateByIdSelective(memoConfigDO);
            //删除当前时间之后的备忘录
            memoInfoService.delByConfigIdAndDate(configId);

            //根据配置生成备忘录详情
            buildMemoInfo(memoConfigDO, tokenUser);

        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteByMemoId(String memoInfoId, TokenUser tokenUser) {
        MemoInfoVO memoInfoVO = memoInfoService.selectById(memoInfoId, tokenUser.getSiteId());
        if (memoInfoVO == null) {
            return;
        }
        String configId = memoInfoVO.getConfigId();
        if (StringUtils.isNotBlank(configId)) {
            deleteByIds(configId);
            memoInfoService.delByConfigIdAndDate(configId);
        }
    }


    /**
     * 根据查询参数，构建example

     * @param memoConfigQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(MemoConfigQuery memoConfigQuery, String siteId) {
        Example example = new Example(MemoConfigDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        // 排序
        ExampleKit.setExampleOrder(example,memoConfigQuery.getOrders());
        return example;
    }
}




